package org.esti.controller;

import org.esti.model.User;
import org.esti.model.utils.LevelPropertyEditor;
import org.esti.service.LevelService;
import org.esti.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * @author Artem Loginov (logart)
 */

/**
 * This controller is used for providing mapping between request and view
 * and showing profile information.
 * For example: forms for view and editing profile
 */
@Controller
@RequestMapping(value = "/{login}/profile")
public class ProfileController {

    private static final String USER_MODEL_ATTRIBUTE_NAME = "user";

    @Autowired
    private UserService userService;

    @Autowired
    private LevelService levelService;


    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        CustomDateEditor editor = new CustomDateEditor(new SimpleDateFormat("dd/MM/yyyy"), true);
        binder.registerCustomEditor(Date.class, editor);
        binder.registerCustomEditor(org.esti.model.Level.class, new LevelPropertyEditor(levelService));

    }

    /**
     * Show edit user profile form
     *
     * @param login of user whose profile we will edit
     * @param model set of parameters which will be passed to view. In this case user fields(name, birthday, etc.)
     * @return name of view which will be render
     */
    @RequestMapping(params = {"action=edit"}, method = RequestMethod.GET)
    public String showEditProfileForm(
            @PathVariable String login,
            Model model) {

        User user = userService.getUserByLogin(login);
        model.addAttribute(USER_MODEL_ATTRIBUTE_NAME, user);

        model.addAttribute("levels", levelService.getAvailableLevels());

        return "edit_profile";
    }

    /**
     * Update user in database using information from parameters
     *
     * @param name       new user name
     * @param middleName new user middle name
     * @param surname    new user surname
     * @param birthday   new user date of birthday
     * @param login      of user whose account data will be updated
     * @param model      set of parameters which will be passed to view. In this case user fields(name, birthday, etc.)
     * @return name of view which will be render
     */
    @RequestMapping(params = {"action=edit"}, method = RequestMethod.POST)
    public String processEditProfileForm(
            @RequestParam String name,
            @RequestParam String middleName,
            @RequestParam String surname,
            @RequestParam Date birthday,
            @RequestParam(required = false) org.esti.model.Level level,
            @PathVariable String login,
            Model model) {

        User user = userService.getUserByLogin(login);

        user.setName(name);
        user.setMiddleName(middleName);
        user.setSurname(surname);
        user.setBirthday(birthday);

        if (null != level) {
            user.setLevel(level);
        }

        userService.updateUser(user);

        model.addAttribute(USER_MODEL_ATTRIBUTE_NAME, user);

        return "redirect:/" + user.getLogin() + "/profile?action=edit";
    }

    /**
     * Shows user profile
     *
     * @param login      of user whose profile we want to show
     * @param firstLogin flag of help information. If set to true user will see some additional "first step" information.
     * @param model      set of parameters which will be passed to view. Fro example user and his appraisal.
     * @return name of view which will be render
     */
    @RequestMapping()
    public String showProfile(
            @PathVariable String login,
            @RequestParam(value = "first_login", required = false) Boolean firstLogin,
            Model model) {

        model.addAttribute("first_login", firstLogin);

        User user = userService.getUserByLogin(login);
        model.addAttribute(USER_MODEL_ATTRIBUTE_NAME, user);

        return "view_profile";
    }

    /**
     * Show change avatar form.
     * This form is used to upload new photo of user.
     *
     * @return name of view which will be render
     */
    @RequestMapping(params = {"action=change_avatar"}, method = RequestMethod.GET)
    public String showChangeAvatarForm(@PathVariable String login, Model model) {

        User user = userService.getUserByLogin(login);
        model.addAttribute(USER_MODEL_ATTRIBUTE_NAME, user);

        return "edit_avatar";
    }

    @RequestMapping(params = {"action=change_avatar"}, method = RequestMethod.POST)
    public String processChangeAvatar(
            @RequestParam(value = "photo", required = true) MultipartFile image,
            @PathVariable String login,
            Model model) {

        User user = userService.getUserByLogin(login);
        model.addAttribute(USER_MODEL_ATTRIBUTE_NAME, user);

        userService.updatePhoto(login, image);

        return "edit_avatar";
    }
}
